﻿#region Usings

using System;
using System.Linq;
using System.Web.Mvc;
using XPressify.Data.Helpers;
using XPressify.Data;
using XPressify.Helpers;
using XPressify.Models;

#endregion

namespace XPressify.Controllers
{
    public abstract class SubjectController : BaseController
    {
        [Authorize]
        public ActionResult ConfirmRelationship(Guid id)
        {
            var rel = Repository.AsQueryable<Relationship>().SingleOrDefault(x => x.Id == id);
            
            if (rel == null)
            {
                // notify
                var model = new NotifyModel
                {
                    Title = "Confirm",
                    Header = "Confirming failed.",
                    Body = "Request doesn't exist anymore.",
                    NotificationType = NotificationType.Notification
                };
                return RedirectToAction("Notify", "Home", model);
            }



            var user = CurrentUser;


            //if its blocked or already confirmed then we dont do nothing
            if(rel.Status == RelationshipStatus.Blocked || rel.Status == RelationshipStatus.Confirmed)
            {
                return  RedirectToAction("ProfileView", "Profile", new {id = user.Id});
            }

            rel.Status = RelationshipStatus.Confirmed;

            if(rel.BaseSubject.Id != user.Id && rel.BaseSubject2.Id != user.Id)
            {
                // notify
                var model = new NotifyModel
                {
                    Title = "Confirm",
                    Header = "Confirming failed.",
                    Body = "Login with requested account and try again.",
                    NotificationType = NotificationType.Notification
                };
                return RedirectToAction("Notify", "Home", model);
            }

            //create a post
            var baseSub = rel.BaseSubject.Id == user.Id ? rel.BaseSubject2 : rel.BaseSubject;
            
            if (baseSub.Type == SubjectType.Group)
            {
                var group = (Group)baseSub;
                CreateGroupPost(rel, group);
            }
            else if (baseSub.Type == SubjectType.Event)
            {
                var @event = (Event)baseSub;
                CreateEventPost(rel, @event);
            }
            else if (baseSub.Type == SubjectType.Page)
            {
                var page = (Page)baseSub;
                CreatePagePost(rel, page);
            }
            else if (baseSub.Type == SubjectType.User)
            {
                var friend = (User)baseSub;
                if (rel.RelationType == RelationshipType.FriendOf)
                {
                    CreateFriendshipPost(user, friend, rel);
                    CreateFriendshipPost(friend, user, rel);

                    //make AcceptedYourRelationshipRequest notification
                    var newNotification = new Notification()
                    {
                        Active = true,
                        BaseSubject = rel.BaseSubject,
                        Created = DateTime.Now,
                        Id = Guid.NewGuid(),
                        Type = BaseMessageType.Notification
                    };
                    var viewData2 = new
                    {
                        UserId = rel.BaseSubject2.Id,
                        UserFullname = rel.BaseSubject2.FullName,
                        RelationshipType = "friend"
                    };
                    var viewDictionary2 = viewData2.ToViewDataDictionary();
                    newNotification.Content = ControlToString("~/Views/Notification/AcceptedYourRelationshipRequest.cshtml", viewDictionary2);
                    Repository.AddObject(newNotification);

                    Repository.SaveChanges();
                }
                else if (rel.RelationType == RelationshipType.EngagedWith ||  // if its love relationship with some choosed user
                         rel.RelationType == RelationshipType.InRelationshipWith ||
                         rel.RelationType == RelationshipType.ItsComplicatedWith || 
                         rel.RelationType == RelationshipType.MarriedWith ||
                         rel.RelationType == RelationshipType.OpenRelationshipWith)
                {
                    CreateLoveRelationshipPost(user, (User)baseSub, rel);
                    CreateLoveRelationshipPost((User)baseSub, user, rel);

                    //make AcceptedYourRelationshipRequest notification
                    var newNotification = new Notification()
                    {
                        Active = true,
                        BaseSubject = rel.BaseSubject,
                        Created = DateTime.Now,
                        Id = Guid.NewGuid(),
                        Type = BaseMessageType.Notification
                    };
                    var viewData2 = new
                    {
                        UserId = rel.BaseSubject2.Id,
                        UserFullname = rel.BaseSubject2.FullName,
                        RelationshipType = "love"
                    };
                    var viewDictionary2 = viewData2.ToViewDataDictionary();
                    newNotification.Content = ControlToString("~/Views/Notification/AcceptedYourRelationshipRequest.cshtml", viewDictionary2);
                    Repository.AddObject(newNotification);

                    Repository.SaveChanges();
                }
                else // family relationship
                {
                    User requested = (User)rel.BaseSubject;
                    User otherUser = (User)rel.BaseSubject2;
                    //requsted is the one that hase same id as relationship name // special case
                    if(rel.BaseSubject.Id.ToString() == rel.Name)
                    {
                        requested =  (User)rel.BaseSubject;
                        otherUser = (User) rel.BaseSubject2;
                    }
                    else
                    {
                        requested =  (User)rel.BaseSubject2;
                        otherUser = (User)rel.BaseSubject;
                    }

                    //make AcceptedYourRelationshipRequest notification
                    var newNotification = new Notification()
                    {
                        Active = true,
                        BaseSubject = requested,
                        Created = DateTime.Now,
                        Id = Guid.NewGuid(),
                        Type = BaseMessageType.Notification
                    };
                    
                    var viewData2 = new
                    {
                        UserId = otherUser.Id,
                        UserFullname = otherUser.FullName,
                        RelationshipType = "family"
                    };
                    var viewDictionary2 = viewData2.ToViewDataDictionary();
                    newNotification.Content = ControlToString("~/Views/Notification/AcceptedYourRelationshipRequest.cshtml", viewDictionary2);
                    Repository.AddObject(newNotification);

                    Repository.SaveChanges();
                }
            }

            Repository.SaveChanges();

            return ConfirmRelationshipNotification(rel);
        }

        [Authorize]
        public ActionResult PostponeRelationship(Guid id)
        {
            var rel = Repository.AsQueryable<Relationship>().SingleOrDefault(x => x.Id == id);
            if (rel == null)
            {
                // notify
                var model = new NotifyModel
                {
                    Title = "Confirm",
                    Header = "Confirming failed.",
                    Body = "Request doesn't exist anymore.",
                    NotificationType = NotificationType.Notification
                };
                return RedirectToAction("Notify", "Home", model);
            }

            //if its blocked or confirmed then we dont do nothing
            if(rel.Status == RelationshipStatus.Blocked ||rel.Status == RelationshipStatus.Confirmed)
            {
                var user = CurrentUser;
                return RedirectToAction("ProfileView", "Profile", new { id = user.Id });
            }

            if (rel.Status != RelationshipStatus.Confirmed)
            {
                rel.Status = RelationshipStatus.Postponed;
                Repository.SaveChanges();
                return PostponeRelationshipNotification(rel);
            }
            return PostponeFailedRelationshipNotification(rel);
        }

        [Authorize]
        public ActionResult DeleteRelationship(Guid id)
        {
            var rel = Repository.AsQueryable<Relationship>().SingleOrDefault(x => x.Id == id);
            if (rel != null)
            {
                Repository.DeleteObject(rel);
                Repository.SaveChanges();
            }
            // notify
            var model = new NotifyModel
            {
                Title = "Delete",
                Header = "",
                Body = "Delete was successful.",
                NotificationType = NotificationType.Notification
            };
            return RedirectToAction("Notify", "Home", model);
        }

        [Authorize]
        public ActionResult ConfirmAdminRelationship(Guid id)
        {
            //this is a temporary relationship till user doesnt accept it and we will delete it
            var rel = Repository.AsQueryable<Relationship>().SingleOrDefault(x => x.Id == id);

            
            var adminUser = rel.BaseSubject;
            var subject = rel.BaseSubject2;

            var previousAdminPreviousRelationships =
                Repository.AsQueryable<Relationship>().SingleOrDefault(
                    r => r.BaseSubject2.Id == subject.Id && r.BaseSubject.Id != adminUser.Id &&
                         r.RelationType == RelationshipType.AdministratorOf && r.Status == RelationshipStatus.Confirmed);

            //we make previous admin a member only
            previousAdminPreviousRelationships.RelationType = RelationshipType.MemberOf;
            previousAdminPreviousRelationships.Description = RelationshipType.MemberOfText;
            previousAdminPreviousRelationships.Name = RelationshipType.MemberOfText;

            //this is previous member relationship of futured administrator
            var futureAdminPreviousRelationships =
                Repository.AsQueryable<Relationship>().SingleOrDefault(
                    r => r.BaseSubject2.Id == subject.Id && r.BaseSubject.Id == adminUser.Id &&
                         r.RelationType == RelationshipType.MemberOf && r.Status == RelationshipStatus.Confirmed);
            
            // we make it to administrator relationship
            futureAdminPreviousRelationships.RelationType = RelationshipType.AdministratorOf;
            futureAdminPreviousRelationships.Description = RelationshipType.AdministratorOfText;
            futureAdminPreviousRelationships.Name = RelationshipType.AdministratorOfText;
            Repository.SaveChanges();

            //other previous relationships that were requested for administrator are going to be deleted
            var otherPreviousRelationships =
                Repository.AsQueryable<Relationship>().Where(
                    r => r.BaseSubject2.Id == subject.Id &&
                         r.RelationType == RelationshipType.AdministratorOf && r.Status != RelationshipStatus.Confirmed);

            foreach (var previousRelationship in otherPreviousRelationships)
            {
                Repository.DeleteObject(previousRelationship);
            }
            Repository.SaveChanges();

            //create a notification
            var members = Repository.GetMembersOf(subject.Id).ToList();
            var subjectType = "";
            if(subject.Type == SubjectType.Event)
            {
                subjectType = "event";
            }
            else if (subject.Type == SubjectType.Group)
            {
                subjectType = "group";
            }
            else if (subject.Type == SubjectType.Page)
            {
                subjectType = "page";
            }
            var admin = Repository.GetAdminOf(subject.Id);
            members.Add(admin);
            foreach (var member in members)
            {
                //GroupEventPageChange notification
                var newNotification = new Notification()
                {
                    Active = true,
                    BaseSubject = member,
                    Created = DateTime.Now,
                    Id = Guid.NewGuid(),
                    Type = BaseMessageType.Notification
                };
                var viewData3 = new
                {
                    BaseSubjectType = subjectType,
                    SubjectId = subject.Id,
                    SubjectFullname = subject.FullName,
                    Value = "Administrator",
                    Value2 = ""
                };

                var viewDictionary3 = viewData3.ToViewDataDictionary();
                newNotification.Content = ControlToString("~/Views/Notification/GroupEventPageChange.cshtml", viewDictionary3);
                Repository.AddObject(newNotification);
            }
            Repository.SaveChanges();

            if (futureAdminPreviousRelationships.BaseSubject2.Type == SubjectType.Event)
            {
                return RedirectToAction("EventDetails", "Event", new { id = futureAdminPreviousRelationships.BaseSubject2.Id });
            }
            if (futureAdminPreviousRelationships.BaseSubject2.Type == SubjectType.Group)
            {
                return RedirectToAction("GroupDetails", "Group", new { id = futureAdminPreviousRelationships.BaseSubject2.Id });
            }
            if (futureAdminPreviousRelationships.BaseSubject2.Type == SubjectType.Page)
            {
                return RedirectToAction("PageDetails", "Page", new { id = futureAdminPreviousRelationships.BaseSubject2.Id });
            }
            return RedirectToAction("NewsFeed", "Home", new {});
        }

        public abstract ActionResult ConfirmRelationshipNotification(Relationship relationship);
        public abstract ActionResult PostponeRelationshipNotification(Relationship relationship);
        public abstract ActionResult PostponeFailedRelationshipNotification(Relationship relationship);

        #region Create post
        public void CreateGroupPost(Relationship rel, Group group)
        {
            var user = CurrentUser;
            var newPost = new Post()
            {
                BaseObject = rel,
                BaseSubject = user,
                Created = DateTime.Now,
                Description = "Joined a group", 
                PostType = PostType.Post,
                Type = BaseMessageType.Post,
                Id = Guid.NewGuid(),
                Title = "Joined a group",
                CommentType = CommentType.PostWithItsComments
            };


            string profilePicturePath = Repository.GetProfilePicturePath(user.Id);

            var viewData = new
            {
                YourFullName = user.FullName,
                YourId = user.Id,
                Type = "group",
                Id = group.Id,
                Created = newPost.Created,
                PostId = newPost.Id,
                ProfilePicturePath = profilePicturePath,
                Name = group.Name
            };

            var viewDictionary = viewData.ToViewDataDictionary();
            newPost.Content = ControlToString("~/Views/Post/Joined.cshtml", viewDictionary);
            Repository.AddObject(newPost);
            Repository.SaveChanges();
        }

        public void CreateEventPost(Relationship rel, Event @event)
        {
            var user = CurrentUser;
            var newPost = new Post()
            {
                BaseObject = rel,
                BaseSubject = user,
                Created = DateTime.Now,
                Description = "Joined a event",
                PostType = PostType.Post,
                Type = BaseMessageType.Post,
                Id = Guid.NewGuid(),
                Title = "Joined a event",
                CommentType = CommentType.PostWithItsComments
            };

            string profilePicturePath = Repository.GetProfilePicturePath(user.Id);

            var viewData = new
            {
                YourFullName = user.FullName,
                YourId = user.Id,
                Type = "event",
                Id = @event.Id,
                Created = newPost.Created,
                PostId = newPost.Id,
                ProfilePicturePath = profilePicturePath,
                Name = @event.Name
            };
            var viewDictionary = viewData.ToViewDataDictionary();
            newPost.Content = ControlToString("~/Views/Post/Joined.cshtml", viewDictionary);
            Repository.AddObject(newPost);
            Repository.SaveChanges();
        }

        public void CreatePagePost(Relationship rel, Page page)
        {
            var user = CurrentUser;
            var newPost = new Post()
            {
                BaseObject = rel,
                BaseSubject = user,
                Created = DateTime.Now,
                Description = "Joined a page", 
                PostType = PostType.Post,
                Type = BaseMessageType.Post,
                Id = Guid.NewGuid(),
                Title = "Joined a page",
                CommentType = CommentType.PostWithItsComments
            };

            string profilePicturePath = Repository.GetProfilePicturePath(user.Id);

            var viewData = new
            {
                YourFullName = user.FullName,
                YourId = user.Id,
                Type = "page",
                Id = page.Id,
                Created = newPost.Created,
                PostId = newPost.Id,
                ProfilePicturePath = profilePicturePath,
                Name = page.Name
            };
            var viewDictionary = viewData.ToViewDataDictionary();
            newPost.Content = ControlToString("~/Views/Post/Joined.cshtml", viewDictionary);
            Repository.AddObject(newPost);
            Repository.SaveChanges();
        }

        public void CreateFriendshipPost(User firstUser, User secondUser, Relationship rel)
        {
            var newPost = new Post()
            {
                BaseObject = rel,
                BaseSubject = firstUser,
                Created = DateTime.Now,
                Description = "Become friend",
                PostType = PostType.Post,
                Type = BaseMessageType.Post,
                Id = Guid.NewGuid(),
                Title = "Become friend",
                CommentType = CommentType.PostWithItsComments
            };

            string profilePicturePath =
                Repository.GetProfilePicturePath(firstUser.Id);

            var viewData = new
            {
                FirstUserName = firstUser.FullName,
                FirstUserId = firstUser.Id,
                SecondUserName = secondUser.FullName,
                SecondUserId = secondUser.Id,
                Created = newPost.Created,
                PostId = newPost.Id,
                profilePicturePath = profilePicturePath
            };
            var viewDictionary = viewData.ToViewDataDictionary();
            newPost.Content = ControlToString("~/Views/Post/BecomeFriend.cshtml", viewDictionary);
            Repository.AddObject(newPost);
            Repository.SaveChanges();
        }

        public void CreateLoveRelationshipPost(User currentUser, User friendUser, Relationship relationship)
        {
            //create post
            var newPost = new Post()
            {
                BaseObject = relationship,
                BaseSubject = currentUser,
                Created = DateTime.Now,
                Description = "Love relationship post",
                PostType = PostType.Post,
                Type = BaseMessageType.Post,
                Title = "Love relationship post",
                Id = Guid.NewGuid(),
                CommentType = CommentType.PostWithItsComments
            };

            string profilePicturePath = Repository.GetProfilePicturePath(currentUser.Id);

            var viewData = new
            {
                YourId = currentUser.Id,
                YourFullname = currentUser.FullName,
                RelationshipType = GetLoveRelationTypeName(relationship),
                ExistUser = "true",
                FriendFullname = friendUser.FullName,
                FriendId = friendUser.Id,
                Created = newPost.Created,
                PostId = newPost.Id,
                ProfilePicturePath = profilePicturePath
            };
            var viewDictionary = viewData.ToViewDataDictionary();
            newPost.Content = ControlToString("~/Views/Post/RelationshipStatusChange.cshtml", viewDictionary);
            Repository.AddObject(newPost);
            Repository.SaveChanges();
        }

        #endregion

        #region Get relationship type
        public string GetLoveRelationTypeName(Relationship rel)
        {
            var user = CurrentUser;
            if (rel.RelationType == RelationshipType.EngagedWith)
            {
                return "engaged";
            }
            if (rel.RelationType == RelationshipType.InRelationshipWith)
            {
                return "in relationship";
            }
            if (rel.RelationType == RelationshipType.IsDivorced)
            {
                return "divorced";
            }
            if (rel.RelationType == RelationshipType.IsSingle)
            {
                return "single";
            }
            if (rel.RelationType == RelationshipType.IsWidowed)
            {
                return "widowed";
            }
            if (rel.RelationType == RelationshipType.ItsComplicatedWith)
            {
                return "complicated";
            }
            if (rel.RelationType == RelationshipType.MarriedWith)
            {
                return "married";
            }
            if (rel.RelationType == RelationshipType.OpenRelationshipWith)
            {
                return "in open relationship";
            }
            if (rel.RelationType == RelationshipType.ChildOf && rel.BaseSubject.Id == user.Id)
            {
                return "Parent";
            }
            if (rel.RelationType == RelationshipType.ChildOf && rel.BaseSubject2.Id == user.Id)
            {
                return "Child";
            }
            if (rel.RelationType == RelationshipType.GrandchildOf && rel.BaseSubject.Id == user.Id)
            {
                return "Grand parent";
            }
            if (rel.RelationType == RelationshipType.GrandchildOf && rel.BaseSubject2.Id == user.Id)
            {
                return "Grand child";
            }
            if (rel.RelationType == RelationshipType.SiblingchildOf && rel.BaseSubject.Id == user.Id)
            {
                return "Uncle/Aunt";
            }
            if (rel.RelationType == RelationshipType.SiblingchildOf && rel.BaseSubject2.Id == user.Id)
            {
                return "Nephew/Niece";
            }
            if (rel.RelationType == RelationshipType.SiblingOf)
            {
                return "Sibling";
            }
            if (rel.RelationType == RelationshipType.CousinOf)
            {
                return "Cousin";
            }
            return "";
        }
        #endregion

    }
}